using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Net;

namespace Bludz
{
    class NetworkServer : Singleton<NetworkServer>
    {
        public bool connected;
        NetworkSession session;

        public void init()
        {
            connected = false;

            Guide.ShowSignIn(1, false);

            SignedInGamer.SignedIn += new EventHandler<SignedInEventArgs>(onSignedIn);

            EventServer.get().register("update", update);
        }

        public void onSignedIn(object sender, SignedInEventArgs args)
        {
            if (!joinSession())
                createSession();

            connected = true;

            sendData("test", 1, 2, 3, 4, "what", 1.4);
        }

        public bool joinSession()
        {
            int maxLocalPlayers = 1;
            AvailableNetworkSessionCollection sessions = NetworkSession.Find(
                NetworkSessionType.SystemLink, maxLocalPlayers, null);

            if (sessions.Count > 0)
            {
                log("joining existing session hosted by " + sessions[0].HostGamertag);
                session = NetworkSession.Join(sessions[0]);
                return true;
            }
            else
                return false;
        }

        public void createSession() {
            log("creating a session");

            int maxPlayers = 8, maxLocalPlayers = 1;
            session = NetworkSession.Create(NetworkSessionType.SystemLink,
                maxLocalPlayers, maxPlayers);

            session.AllowJoinInProgress = true;
            session.AllowHostMigration = false;
        }

        public bool sendData(string cmd, params object[] dataArr)
        {
            if (connected)
            {
                PacketWriter packetWriter = new PacketWriter();
                LocalNetworkGamer gamer = session.LocalGamers[0];
                packetWriter.Write(cmd);

                List<object> data = new List<object>(dataArr);

                StringWriter writer = new System.IO.StringWriter();
                XmlSerializer xml = new XmlSerializer(data.GetType());
                xml.Serialize(writer, data);
                string dataString = writer.ToString();
                log("send data " + dataString);
                packetWriter.Write(dataString);

                gamer.SendData(packetWriter, SendDataOptions.None, gamer);
                return true;
            }
            else
                return false;
        }

        public void update(string msgCmd, object[] args)
        {
            if (connected) {
                PacketReader packetReader = new PacketReader();
                LocalNetworkGamer gamer = session.LocalGamers[0];
                if (gamer.IsDataAvailable)
                {
                    NetworkGamer sender;
                    gamer.ReceiveData(packetReader, out sender);

                    string cmd = packetReader.ReadString(),
                        dataString = packetReader.ReadString();
                    log("got data " + dataString);

                    XmlSerializer xml = new XmlSerializer(typeof(List<object>));
                    StringReader reader = new StringReader(dataString);
                    List<object> data = (List<object>)xml.Deserialize(reader);

                    if (cmd == "msg")
                    {
                        object[] msgArgs = new object[data.Count - 1];
                        for (int i = 1; i < data.Count; ++i)
                            msgArgs[i-1] = data[i];
                        EventServer.get().pull((string)data[0], msgArgs);
                    }
                }
            }
        }
    }
}
